package com.xyd.wechat.tools;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.xyd.wechat.common.Constant;
import com.xyd.wechat.common.EventEnum;
import com.xyd.wechat.common.MsgTypeEnum;
import com.xyd.wechat.service.AutoReplyService;
import com.xyd.wechat.service.CustomerService;
import com.xyd.wechat.service.MenuService;
import com.xyd.wechat.service.SubscribeService;
import com.xyd.wechat.vo.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.Set;

@Component
public class WechatHandlerTool {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private Set<String> msgList = new LinkedHashSet<String>();

    @Autowired
    private XmlMapper xmlMapper;

    @Autowired
    private AutoReplyService autoReplyService;

    @Autowired
    private SubscribeService subscribeService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private MenuService menuService;

    public String autoReplyByRobot(String req) {
        Message message = null;
        try {
            // 请求字符串转换成实体对象
            logger.info("请求信息：{}", req);
            message = xmlMapper.readValue(req, Message.class);
            // 判断 微信服务器5秒内没有收到回复，重试的消息不再处理
            if (checkRepetition(message)) {
                return null;
            }
            Message cloneMessage = (Message) message.clone();
            String fromUserName = cloneMessage.getFromUserName();
            cloneMessage.setFromUserName(cloneMessage.getToUserName());
            cloneMessage.setToUserName(fromUserName);
            cloneMessage.setCreateTime(Calendar.getInstance().getTimeInMillis());
            cloneMessage.setSource(Constant.SOURCE_WX);
            if (MsgTypeEnum.EVENT.getType().equals(cloneMessage.getMsgType())) {
                if (EventEnum.SUBSCRIBE.getEvent().equals(cloneMessage.getEvent())) {
                    // 关注事件
                    return subscribeService.welcome(cloneMessage);
                } else if (EventEnum.KF_CLOSE_SESSION.getEvent().equals(cloneMessage.getEvent())) {
                    // 客服对话结束 , 转入机器人对话模式
                    customerService.kfCloseSession(cloneMessage);
                } else if (EventEnum.CLICK.getEvent().equalsIgnoreCase(cloneMessage.getEvent())) {
                    // 菜单事件
                    menuService.menuEventView(cloneMessage);
                }
            } else if (MsgTypeEnum.TEXT.getType().equals(cloneMessage.getMsgType())) {
                // 机器人聊天，自动回复
                Message msg = autoReplyService.autoReplyByRobot(cloneMessage);
                if (msg != null) {
                    String str = xmlMapper.writeValueAsString(msg);
                    logger.info("自动回复响应内容：{}", str);
                    return str;
                }
            }
            return null;
        } catch (Exception e) {
            logger.error("发生异常。", e);
            return null;
        } finally {
            // 响应完成，删除消息ID。以免累计导致对象太大
            msgList.remove(String.valueOf(message.getMsgId()));
            msgList.remove(message.getFromUserName() + message.getCreateTime());
        }
    }

    /**
     * 检查微信服务器的消息是不是重复的
     *
     * @param message
     * @return
     */
    public boolean checkRepetition(Message message) {
        if (message.getMsgId() != null) {
            if (msgList.contains(message.getMsgId().toString())) {
                logger.error("微信服务器重试消息:{}", message.getMsgId());
                return true;
            }
            msgList.add(String.valueOf(message.getMsgId()));
        } else {
            if (msgList.contains(message.getFromUserName() + message.getCreateTime())) {
                logger.error("微信服务器重试消息:{}{}", message.getFromUserName(), message.getCreateTime());
                return true;
            }
            msgList.add(message.getFromUserName() + message.getCreateTime());
        }
        return false;
    }
}
